#ifndef JS_LANG_H
#define JS_LANG_H
#include "js.h"

typedef struct GTY(()) js_symbol_t {
    tree name;
    tree decl;
} js_symbol_t;
typedef js_symbol_t* js_symbol;

DEF_VEC_P(js_symbol);
DEF_VEC_ALLOC_P(js_symbol,gc);

typedef enum {
    OpEQLET=1, /*    = */
    OpMULLET,  /*   *= */
    OpDIVLET,  /*   /= */
    OpMODLET,  /*   %= */
    OpADDLET,  /*   += */
    OpSUBLET,  /*   -= */
    OpLSFTLET, /*  <<= */
    OpRSFTLET, /*  >>= */
    OpSHFTLET, /* >>>= */
    OpANDLET,  /*   &= */
    OpXORLET,  /*   ^= */
    OpORLET,   /*   |= */
    OpPlus,
    OpMinus,
    OpMul,
    OpDiv,
    OpMod,
    OpLshift,
    OpRshift,
    OpShift,
    OpOr,
    OpXor,
    OpAnd,
    OpNot,
    OpLT,
    OpLE,
    OpGT,
    OpGE,
    OpEQ,
    OpNE,
    OpSTREQ,
    OpSTRNE,
    OpPRED_INC,
    OpPRED_DEC,
    OpPOST_INC,
    OpPOST_DEC,
    OpUndef = -1
} JSOperator;

typedef long jsint_t;

extern int js__block_level;
extern VEC(tree,gc) *global_decls;

extern tree write_global_script(tree stmts);
extern void init_builtins(void);
extern tree js_build_id(const char *str);
extern tree js_build_int(jsint_t val);
extern tree js_build_string(const char *str);
extern tree js_build_float_str(const char *buf);
extern tree js_build_this_expr(void);
extern tree js_build_int_object(tree x);
extern tree js_build_float_object(tree x);

extern tree js_build_call_expr(tree f, VEC(tree, gc) *args, bool hasSelf, bool);
extern tree js_build_typeof_expr(tree expr);
extern tree js_build_function_decl(tree id, tree lastexpr, bool declObject);
extern tree js_build_function_type(tree rettype, VEC(tree,gc) *vec);
extern tree js_build_function_object(tree name, tree body);
extern tree js_build_throw_expr(tree expr);
extern tree js_build_array_literal(VEC(tree, gc) *elem);
extern tree js_build_array_expr(tree ref, tree index);

extern tree js_build_op2_expr(JSOperator op, tree l, tree r);
extern tree js_build_op1_expr(JSOperator op, tree r);

extern tree js_build_let_expr(JSOperator op, tree l, tree r);
extern tree js_build_if_expr(tree cond, tree stmt1, tree stmt2);

extern tree js_build_new_expr(tree expr, VEC(tree, gc) *args);
extern tree js_build_while_expr(tree cond, tree body, bool isDoWhile);
extern tree js_build_for_expr(tree init, tree cond, tree expr, tree body);
extern tree js_build_propaty_expr(tree self, tree prop);
extern tree js_get_default_value(tree type);
extern tree js_build_return_stmt(tree expr);
extern void js_parse_file(const char *filename);
extern int js_parse(void);
extern tree js_debug_tree(tree expr);
extern location_t CURRENT_LOCATION(void);
extern void __js_debug__( const char * file, unsigned int lineno,
                  const char * fmt, ... );
#define debug(...)  
#define debug0(...)
#define debug1(...)
//#define debug(...)  __js_debug__( __FILE__, __LINE__, __VA_ARGS__ )
//#ifdef DBG0
//#define debug0(...)  debug(__VA_ARGS__)
//#define DBG1 1
//#define DBG2 1
//#else
//#define debug0(...)
//#endif
//#ifdef DBG1
//#define debug1(...)  debug(__VA_ARGS__)
//#else
//#define debug1(...)
//#endif

/* blocks */
extern tree get_level_stmts(int level);
extern VEC(tree,gc) *get_level_decls(int level);
extern VEC(js_symbol,gc) *get_level_args(int level);

extern void js_append_to_current_stmtlist(tree stmt, int level);
extern void js_append_to_current_decls(tree decl, int level);
extern void js_append_to_current_args(tree arg, int level);
extern tree poplevel(int level, tree stmts);
extern void clear_level_stmts(int level);
extern void clear_level_decls(int level);
extern void clear_level_args(int level);

typedef struct js_location {
    int first_line;
    int first_column;
    int last_line;
    int last_column;
} js_location_t;
#ifndef YYLTYPE
typedef js_location_t YYLTYPE;
#define YYLTYPE YYLTYPE
#endif

/* js-symbol.c */
int js_init_tables (void);
int js_del_tables (void);
tree push_decl_to_symtable(tree name, tree expr);

#endif /* end of include guard: JS_LANG_H */
